home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / workbench / directoryopus4 / dopus4_src / dopus_disk / diskcopy.c < prev    next >
C/C++ Source or Header  |  2000-03-11  |  27KB  |  767 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "diskop.h"
  32.  
  33. enum {
  34.     DISKCOPY_VERIFY,
  35.     DISKCOPY_BUMPNAMES,
  36.     DISKCOPY_DISKCOPY,
  37.     DISKCOPY_CANCEL,
  38.     DISKCOPY_CHECK};
  39.  
  40. struct TagItem
  41.     diskcopy_source_list[]={
  42.         {RO_Type,OBJECT_LISTVIEW},
  43.         {RO_ListViewID,0},
  44.         {RO_Top,1},
  45.         {RO_LeftFine,2},
  46.         {RO_Width,10},
  47.         {RO_Height,6},
  48.         {RO_HeightFine,30},
  49.         {RO_TextNum,STR_DISKCOPY_FROM},
  50.         {RO_TextPos,TEXTPOS_ABOVE},
  51.         {RO_HighRecess,TRUE},
  52.         {TAG_END,0}},
  53.     diskcopy_destination_list[]={
  54.         {RO_Type,OBJECT_LISTVIEW},
  55.         {RO_ListViewID,1},
  56.         {RO_Top,1},
  57.         {RO_Left,33},
  58.         {RO_LeftFine,-18},
  59.         {RO_Width,10},
  60.         {RO_Height,6},
  61.         {RO_HeightFine,30},
  62.         {RO_TextNum,STR_DISKCOPY_TO},
  63.         {RO_TextPos,TEXTPOS_ABOVE},
  64.         {RO_HighRecess,TRUE},
  65.         {TAG_END,0}},
  66.  
  67.     diskcopy_verify_gadget[]={
  68.         {RO_Type,OBJECT_GADGET},
  69.         {RO_GadgetType,GADGET_CHECK},
  70.         {RO_GadgetID,DISKCOPY_VERIFY},
  71.         {RO_Left,14},
  72.         {RO_Top,4},
  73.         {RO_TextNum,STR_FORMAT_VERIFY},
  74.         {RO_TextPos,TEXTPOS_RIGHT},
  75.         {RO_LeftFine,-2},
  76.         {RO_BoolOn,TRUE},
  77.         {TAG_END,0}},
  78.  
  79.     diskcopy_bumpnames_gadget[]={
  80.         {RO_Type,OBJECT_GADGET},
  81.         {RO_GadgetType,GADGET_CHECK},
  82.         {RO_GadgetID,DISKCOPY_BUMPNAMES},
  83.         {RO_Left,14},
  84.         {RO_Top,6},
  85.         {RO_TextNum,STR_BUMP_NAMES},
  86.         {RO_TextPos,TEXTPOS_RIGHT},
  87.         {RO_LeftFine,-2},
  88.         {RO_BoolOn,TRUE},
  89.         {TAG_END,0}},
  90.  
  91.     diskcopy_info_box[]={
  92.         {RO_Type,OBJECT_BORDER},
  93.         {RO_BorderType,BORDER_RECESSED},
  94.         {RO_LeftFine,2},
  95.         {RO_Top,7},
  96.         {RO_TopFine,36},
  97.         {RO_Width,43},
  98.         {RO_WidthFine,-4},
  99.         {RO_Height,1},
  100.         {RO_HeightFine,4},
  101.         {TAG_END,0}},
  102.  
  103.     diskcopy_diskcopy_gadget[]={
  104.         {RO_Type,OBJECT_GADGET},
  105.         {RO_GadgetType,GADGET_BOOLEAN},
  106.         {RO_GadgetID,DISKCOPY_DISKCOPY},
  107.         {RO_Top,8},
  108.         {RO_TopFine,45},
  109.         {RO_Width,13},
  110.         {RO_Height,1},
  111.         {RO_HeightFine,4},
  112.         {RO_TextNum,STR_DISKCOPY_DISKCOPY},
  113.         {RO_TextPos,TEXTPOS_CENTER},
  114.         {RO_HighRecess,TRUE},
  115.         {TAG_END,0}},
  116.  
  117.     diskcopy_check_gadget[]={
  118.         {RO_Type,OBJECT_GADGET},
  119.         {RO_GadgetType,GADGET_BOOLEAN},
  120.         {RO_GadgetID,DISKCOPY_CHECK},
  121.         {RO_Left,15},
  122.         {RO_Top,8},
  123.         {RO_TopFine,45},
  124.         {RO_Width,13},
  125.         {RO_Height,1},
  126.         {RO_HeightFine,4},
  127.         {RO_TextNum,STR_DISKCOPY_CHECK},
  128.         {RO_TextPos,TEXTPOS_CENTER},
  129.         {RO_HighRecess,TRUE},
  130.         {TAG_END,0}},
  131.  
  132.     diskcopy_cancel_gadget[]={
  133.         {RO_Type,OBJECT_GADGET},
  134.         {RO_GadgetType,GADGET_BOOLEAN},
  135.         {RO_GadgetID,DISKCOPY_CANCEL},
  136.         {RO_Left,30},
  137.         {RO_Top,8},
  138.         {RO_TopFine,45},
  139.         {RO_Width,13},
  140.         {RO_Height,1},
  141.         {RO_HeightFine,4},
  142.         {RO_TextNum,STR_FORMAT_EXIT},
  143.         {RO_TextPos,TEXTPOS_CENTER},
  144.         {RO_HighRecess,TRUE},
  145.         {TAG_END,0}},
  146.  
  147.     *diskcopy_gadgets[]={
  148.         diskcopy_verify_gadget,
  149.         diskcopy_bumpnames_gadget,
  150.         diskcopy_diskcopy_gadget,
  151.         diskcopy_check_gadget,
  152.         diskcopy_cancel_gadget,
  153.         NULL};
  154.  
  155. /* prototypes */
  156. void show_diskcopy_info(struct RequesterBase *reqbase,Object_Border *border,char *name);
  157. void bump_disk_name(char *disk);
  158. /* end of prototypes */
  159.  
  160. void diskop_diskcopy(vis,portname,argc,argv)
  161. struct VisInfo *vis;
  162. char *portname;
  163. int argc;
  164. char *argv[];
  165. {
  166.     struct RequesterBase diskcopyreq;
  167.     struct Window *window;
  168.     struct IntuiMessage *msg;
  169.     Object_Border *infobox;
  170.     struct DOpusListView *sourcelist,*destinationlist,*view;
  171.     struct Gadget *gadlist;
  172.     ULONG class;
  173.     USHORT code,gadgetid;
  174.     APTR iaddress;
  175.     int a,b,gadcount=0,ignorechange=0;
  176.     int source=-1,dest=-1,startverify=0,bumpnames=0,oldsel;
  177.     int startcheck=0;
  178.     struct DOpusRemember *destkey=NULL;
  179.  
  180.     diskcopyreq.rb_width=43;
  181.     diskcopyreq.rb_height=9;
  182.     diskcopyreq.rb_widthfine=16;
  183.     diskcopyreq.rb_heightfine=61;
  184.     diskcopyreq.rb_leftoffset=8;
  185.     diskcopyreq.rb_topoffset=8;
  186.     diskcopyreq.rb_flags=0;
  187.  
  188.     fill_out_req(&diskcopyreq,vis);
  189.  
  190.     diskcopyreq.rb_privateflags=0;
  191.     diskcopyreq.rb_screenname=NULL;
  192.  
  193.     if (diskcopyreq.rb_screen && !(vis->vi_flags&VISF_BORDERS)) {
  194.         diskcopyreq.rb_flags|=RBF_STRINGS;
  195.         diskcopyreq.rb_title=NULL;
  196.     }
  197.     else {
  198.         diskcopyreq.rb_flags|=RBF_BORDERS|RBF_CLOSEGAD|RBF_STRINGS;
  199.         diskcopyreq.rb_title=string_table[STR_DISKCOPY_DISKCOPY];
  200.     }
  201.  
  202.     diskcopyreq.rb_extend=NULL;
  203.     diskcopyreq.rb_idcmpflags=0;
  204.     diskcopyreq.rb_string_table=string_table;
  205.  
  206.     if (!(window=OpenRequester(&diskcopyreq)) ||
  207.         !(gadlist=addreqgadgets(&diskcopyreq,diskcopy_gadgets,0,&gadcount)) ||
  208.         !(infobox=(Object_Border *)
  209.             AddRequesterObject(&diskcopyreq,diskcopy_info_box)) ||
  210.         !(sourcelist=(struct DOpusListView *)
  211.             AddRequesterObject(&diskcopyreq,diskcopy_source_list)) ||
  212.         !(sourcelist->items=get_device_list(&diskcopyreq.rb_memory,NULL)) ||
  213.         !(destinationlist=(struct DOpusListView *)
  214.             AddRequesterObject(&diskcopyreq,diskcopy_destination_list))) {
  215.         CloseRequester(&diskcopyreq);
  216.         return;
  217.     }
  218.  
  219.     fix_listview(&diskcopyreq,sourcelist);
  220.     fix_listview(&diskcopyreq,destinationlist);
  221.  
  222.     select_device(sourcelist,NULL);
  223.     get_env("diskcopy",gadlist,gadcount,sourcelist);
  224.  
  225.     oldsel=sourcelist->itemselected;
  226.  
  227.     for (a=0;a<argc;a++) {
  228.         if (LStrCmpI(argv[a],"verify")==0) startverify=1;
  229.         else if (LStrnCmpI(argv[a],"bump",4)==0) bumpnames=1;
  230.         else if (LStrnCmpI(argv[a],"check",5)==0) startcheck=1;
  231.         else {
  232.             if (source==-1) {
  233.                 for (b=0;sourcelist->items[b];b++) {
  234.                     if (LStrCmpI(argv[a],sourcelist->items[b])==0) {
  235.                         source=b;
  236.                         sourcelist->itemselected=b;
  237.                         destinationlist->items=
  238.                             get_device_list(&destkey,sourcelist->items[b]);
  239.                         break;
  240.                     }
  241.                 }
  242.             }
  243.             else if (dest==-1 && destinationlist->items) {
  244.                 for (b=0;destinationlist->items[b];b++) {
  245.                     if (LStrCmpI(argv[a],destinationlist->items[b])==0) {
  246.                         dest=b;
  247.                         destinationlist->itemselected=b;
  248.                         break;
  249.                     }
  250.                 }
  251.             }
  252.         }
  253.     }
  254.  
  255.     if (source>-1 && dest==-1) {
  256.         LFreeRemember(&destkey);
  257.         destinationlist->items=NULL;
  258.         sourcelist->itemselected=oldsel;
  259.         startverify=bumpnames=0;
  260.     }
  261.  
  262.     if (!destinationlist->items) {
  263.         destinationlist->items=
  264.             get_device_list(&destkey,sourcelist->items[sourcelist->itemselected]);
  265.         select_device(destinationlist,sourcelist->items[sourcelist->itemselected]);
  266.         sourcelist->next=destinationlist;
  267.         if (source==-1) get_env("diskcopy",gadlist,gadcount,sourcelist);
  268.     }
  269.     else sourcelist->next=destinationlist;
  270.  
  271.     if (!(AddListView(sourcelist,2))) {
  272.         CloseRequester(&diskcopyreq);
  273.         LFreeRemember(&destkey);
  274.         return;
  275.     }
  276.     show_sel_item(sourcelist);
  277.  
  278.     if (startverify) gadlist->Flags|=GFLG_SELECTED;
  279.     else if (dest>-1) gadlist->Flags&=~GFLG_SELECTED;
  280.  
  281.     if (bumpnames) gadlist->NextGadget->Flags|=GFLG_SELECTED;
  282.     else if (dest>-1) gadlist->NextGadget->Flags&=~GFLG_SELECTED;
  283.  
  284.     RefreshRequesterObject(&diskcopyreq,NULL);
  285.     RefreshGList(gadlist,window,NULL,gadcount);
  286.     show_diskcopy_info(&diskcopyreq,infobox,sourcelist->items[sourcelist->itemselected]);
  287.  
  288.     if (dest>-1) {
  289.         if (do_diskcopy(&diskcopyreq,
  290.             infobox,
  291.             sourcelist->items[sourcelist->itemselected],
  292.             destinationlist->items[destinationlist->itemselected],
  293.             (gadlist->Flags&GFLG_SELECTED),
  294.             (gadlist->NextGadget->Flags&GFLG_SELECTED),
  295.             startcheck)) {
  296.             dopus_message(DOPUSMSG_UPDATEDRIVE,
  297.                 (APTR)destinationlist->items[destinationlist->itemselected],
  298.                 portname);
  299.         }
  300.         RemoveListView(sourcelist,2);
  301.         CloseRequester(&diskcopyreq);
  302.         LFreeRemember(&destkey);
  303.         return;
  304.     }
  305.  
  306.     FOREVER {
  307.         while (msg=(struct IntuiMessage *)GetMsg(window->UserPort)) {
  308.             if ((view=(struct DOpusListView *)ListViewIDCMP(sourcelist,msg))==
  309.                 (struct DOpusListView *)-1) {
  310.                 class=msg->Class; code=msg->Code;
  311.                 iaddress=msg->IAddress;
  312.                 ReplyMsg((struct Message *)msg);
  313.  
  314.                 switch (class) {
  315.                     case IDCMP_DISKINSERTED:
  316.                     case IDCMP_DISKREMOVED:
  317.                         if (ignorechange) ignorechange=0;
  318.                         else {
  319.                             show_diskcopy_info(&diskcopyreq,
  320.                                 infobox,
  321.                                 sourcelist->items[sourcelist->itemselected]);
  322.                         }
  323.                         break;
  324.  
  325.                     case IDCMP_VANILLAKEY:  
  326.                         code=toupper(code);
  327.                         switch (code) {
  328.                             case 'V':
  329.                                 gadlist->Flags^=GFLG_SELECTED;
  330.                                 RefreshGList(gadlist,window,NULL,1);
  331.                                 break;
  332.                             case 'B':
  333.                                 gadlist->NextGadget->Flags^=GFLG_SELECTED;
  334.                                 RefreshGList(gadlist,window,NULL,1);
  335.                                 break;
  336.                             case 0x1b:
  337.                                 set_env("diskcopy",gadlist,gadcount,sourcelist);
  338.                                 RemoveListView(sourcelist,2);
  339.                                 CloseRequester(&diskcopyreq);
  340.                                 LFreeRemember(&destkey);
  341.                                 return;
  342.                         }
  343.                         break;
  344.  
  345.                     case IDCMP_GADGETDOWN:
  346.                     case IDCMP_GADGETUP:
  347.                         gadgetid=((struct Gadget *)iaddress)->GadgetID;
  348.                     case IDCMP_CLOSEWINDOW:
  349.                         if (class==IDCMP_CLOSEWINDOW) gadgetid=DISKCOPY_CANCEL;
  350.  
  351.                         switch (gadgetid) {
  352.                             case DISKCOPY_CANCEL:
  353.                                 set_env("diskcopy",gadlist,gadcount,sourcelist);
  354.                                 RemoveListView(sourcelist,2);
  355.                                 CloseRequester(&diskcopyreq);
  356.                                 LFreeRemember(&destkey);
  357.                                 return;
  358.                             case DISKCOPY_DISKCOPY:
  359.                             case DISKCOPY_CHECK:
  360.                                 if (do_diskcopy(&diskcopyreq,
  361.                                     infobox,
  362.                                     sourcelist->items[sourcelist->itemselected],
  363.                                     destinationlist->items[destinationlist->itemselected],
  364.                                     (gadlist->Flags&GFLG_SELECTED),
  365.                                     (gadlist->NextGadget->Flags&GFLG_SELECTED),
  366.                                     (gadgetid==DISKCOPY_CHECK))) {
  367.                                     ignorechange=1;
  368.                                     dopus_message(DOPUSMSG_UPDATEDRIVE,
  369.                                         (APTR)destinationlist->items[destinationlist->itemselected],
  370.                                         portname);
  371.                                 }
  372.                                 break;
  373.                         }
  374.                         break;
  375.                 }
  376.             }
  377.             else if (view) {
  378.                 switch (view->listid) {
  379.                     case 0:
  380.                         LFreeRemember(&destkey);
  381.                         destinationlist->items=get_device_list(&destkey,view->items[view->itemselected]);
  382.                         select_device(destinationlist,view->items[view->itemselected]);
  383.                         RefreshListView(destinationlist,1);
  384.                         show_diskcopy_info(&diskcopyreq,infobox,sourcelist->items[sourcelist->itemselected]);
  385.                         break;
  386.                 }
  387.             }
  388.         }
  389.         Wait(1<<window->UserPort->mp_SigBit);
  390.     }
  391. }
  392.  
  393.  void show_diskcopy_info(reqbase,border,name)
  394.  struct RequesterBase *reqbase;
  395.  Object_Border *border;
  396.  char *name;
  397. {
  398.     char infobuf[60],sizebuf[20];
  399.     BPTR lock;
  400.     struct FileInfoBlock __aligned fib;
  401.     struct InfoData __aligned info;
  402.     struct Process *myproc;
  403.     APTR wsave;
  404.  
  405.     myproc=(struct Process *)FindTask(NULL);
  406.     wsave=myproc->pr_WindowPtr;
  407.     myproc->pr_WindowPtr=(APTR)-1;
  408.  
  409.     border_text(reqbase,border,NULL);
  410.  
  411.     if (name) {
  412.         if (lock=Lock(name,ACCESS_READ)) {
  413.             Info(lock,&info);
  414.             Examine(lock,&fib);
  415.             UnLock(lock);
  416.  
  417.             getsizestring(sizebuf,info.id_NumBlocksUsed*info.id_BytesPerBlock);
  418.             lsprintf(infobuf,string_table[STR_DISKCOPY_INFODISPLAY],fib.fib_FileName,sizebuf);
  419.  
  420.             border_text(reqbase,border,infobuf);
  421.         }
  422.         else border_text(reqbase,border,string_table[STR_DISKCOPY_NODISK]);
  423.     }
  424.     myproc->pr_WindowPtr=wsave;
  425. }
  426.  
  427. do_diskcopy(reqbase,border,source,dest,verify,bump,check)
  428. struct RequesterBase *reqbase;
  429. Object_Border *border;
  430. char *source,*dest;
  431. int verify,bump,check;
  432. {
  433.     struct IOExtTD *device_req[2];
  434.     struct MsgPort *device_port[2];
  435.     struct DeviceNode *source_node,*dest_node;
  436.     struct FileSysStartupMsg *startup;
  437.     struct DosEnvec *dosenvec;
  438.     struct Requester busyreq;
  439.     ULONG tracksize,lowtrack[2],numtracks,memtype,deviceunit[2],deviceflags[2],track;
  440.     ULONG trackcount,trackmod,curtrack,offset;
  441.     char devicename[2][40],infobuf[80];
  442.     int a,b,drives,abort=0,err=0,cmpsize,txt=-1;
  443.     char *buffer=NULL,*dev_table[2];
  444.     ULONG *verifybuffer=NULL,*cmpbuffer;
  445.     struct DOpusRemember *memkey=NULL;
  446.  
  447.     if (!source || !dest ||
  448.         !(source_node=find_device(source)) ||
  449.         !(dest_node=find_device(dest))) return(0);
  450.  
  451.     if (check) verify=1;
  452.     if (LStrCmpI(source,dest)==0) drives=1;
  453.     else drives=2;
  454.  
  455.     dev_table[0]=source; dev_table[1]=dest;
  456.  
  457.     for (a=0;a<2;a++) {
  458.         device_port[a]=NULL;
  459.         device_req[a]=NULL;
  460.     }
  461.  
  462.     startup=(struct FileSysStartupMsg *)BADDR(source_node->dn_Startup);
  463.     BtoCStr((BPTR)startup->fssm_Device,devicename[0],40);
  464.     deviceunit[0]=startup->fssm_Unit;
  465.     deviceflags[0]=startup->fssm_Flags;
  466.  
  467.     dosenvec=(struct DosEnvec *)BADDR(startup->fssm_Environ);
  468.     tracksize=(dosenvec->de_SizeBlock<<2)*dosenvec->de_Surfaces*dosenvec->de_BlocksPerTrack;
  469.     lowtrack[0]=dosenvec->de_LowCyl;
  470.     numtracks=dosenvec->de_HighCyl-dosenvec->de_LowCyl+1;
  471.     memtype=dosenvec->de_BufMemType;
  472.  
  473.     Forbid();
  474.  
  475.     if (drives==2) trackcount=1;
  476.     else {
  477.         if ((trackcount=AvailMem(memtype|MEMF_LARGEST)/tracksize)>1) {
  478.             if (numtracks%trackcount) {
  479.                 trackmod=(numtracks/trackcount)+1;
  480.                 trackcount=numtracks/trackmod;
  481.             }
  482.         }
  483.     }
  484.  
  485.     if (trackcount>0) buffer=LAllocRemember(&memkey,tracksize*trackcount,memtype);
  486.  
  487.     Permit();
  488.  
  489.     if (!buffer) {
  490.         border_text(reqbase,border,string_table[STR_MEMORY_ERROR]);
  491.         return(0);
  492.     }
  493.  
  494.     cmpbuffer=(ULONG *)buffer;
  495.  
  496.     if (verify) {
  497.         verifybuffer=(ULONG *)LAllocRemember(&memkey,tracksize,memtype);
  498.         cmpsize=tracksize>>2;
  499.     }
  500.     if (check && !verifybuffer) {
  501.         border_text(reqbase,border,string_table[STR_MEMORY_ERROR]);
  502.         return(0);
  503.     }
  504.  
  505.     startup=(struct FileSysStartupMsg *)BADDR(dest_node->dn_Startup);
  506.     BtoCStr((BPTR)startup->fssm_Device,devicename[1],40);
  507.     deviceunit[1]=startup->fssm_Unit;
  508.     deviceflags[1]=startup->fssm_Flags;
  509.  
  510.     dosenvec=(struct DosEnvec *)BADDR(startup->fssm_Environ);
  511.     lowtrack[1]=dosenvec->de_LowCyl;
  512.  
  513.     for (a=0;a<2;a++) {
  514.         if (!(device_port[a]=LCreatePort(NULL,0)) ||
  515.             !(device_req[a]=(struct IOExtTD *)
  516.             LCreateExtIO(device_port[a],sizeof(struct IOExtTD)))) break;
  517.         if (OpenDevice(devicename[a],deviceunit[a],
  518.             (struct IORequest *)device_req[a],deviceflags[a])) {
  519.             LDeleteExtIO((struct IORequest *)device_req[a]);
  520.             device_req[a]=NULL;
  521.             break;
  522.         }
  523.     }
  524.  
  525.     if (a==2) {
  526.         InitRequester(&busyreq);
  527.         busyreq.Flags=NOISYREQ;
  528.         Request(&busyreq,reqbase->rb_window);
  529.         SetBusyPointer(reqbase->rb_window);
  530.  
  531.         if (drives==2) {
  532.             border_text(reqbase,border,string_table[STR_CHECKING_DISKS]);
  533.  
  534.             for (a=0;a<2;a++) {
  535.                 if (!(check_disk(reqbase,device_req[a],dev_table[a],(check)?0:a))) break;
  536.                 if (a==1 && !check && !(check_blank_disk(reqbase,dev_table[a],
  537.                     string_table[STR_DISKCOPY_DISKCOPY])))
  538.                     break;
  539.             }
  540.         }
  541.         else a=2;
  542.  
  543.         if (a==2) {
  544.             inhibit_drive(source,DOSTRUE);
  545.             if (drives==2) inhibit_drive(dest,DOSTRUE);
  546.  
  547.             for (a=0;a<drives;a++) drive_motor(device_req[a],1);
  548.  
  549.             for (track=0;track<numtracks;track+=trackcount) {
  550.  
  551.                 offset=(lowtrack[0]+track)*tracksize;
  552.  
  553.                 if (drives==1) {
  554.                     lsprintf(infobuf,string_table[STR_DISKCOPY_INSERTSOURCE],source);
  555.                     border_text(reqbase,border,infobuf);
  556.                     drive_motor(device_req[0],0);
  557.                     if (!(check_error(reqbase,infobuf,STR_PROCEED)) ||
  558.                         !(check_disk(reqbase,device_req[0],source,0))) {
  559.                         err=ERROR_ABORTED;
  560.                         break;
  561.                     }
  562.                     drive_motor(device_req[0],1);
  563.                 }
  564.  
  565.                 for (curtrack=0;curtrack<trackcount;curtrack++) {
  566.  
  567.                     lsprintf(infobuf,string_table[STR_DISKCOPY_READING],
  568.                         track+curtrack,numtracks-curtrack-track-1);
  569.                     border_text(reqbase,border,infobuf);
  570.  
  571.                     if (check_abort(reqbase->rb_window)) {
  572.                         abort=1;
  573.                         err=ERROR_ABORTED;
  574.                         break;
  575.                     }
  576.  
  577.                     FOREVER {
  578.                         device_req[0]->iotd_Req.io_Command=CMD_READ;
  579.                         device_req[0]->iotd_Req.io_Data=(APTR)&buffer[curtrack*tracksize];
  580.                         device_req[0]->iotd_Req.io_Offset=offset;
  581.                         device_req[0]->iotd_Req.io_Length=tracksize;
  582.  
  583.                         if (!(DoIO((struct IORequest *)device_req[0]))) break;
  584.  
  585.                         lsprintf(infobuf,string_table[STR_DISKCOPY_READERROR],track+curtrack);
  586.                         border_text(reqbase,border,infobuf);
  587.                         if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  588.                             abort=1;
  589.                             err=ERROR_FAILED;
  590.                             break;
  591.                         }
  592.                     }
  593.  
  594.                     if (abort) break;
  595.                     offset+=tracksize;
  596.                 }
  597.  
  598.                 if (abort) break;
  599.  
  600.                 offset=(lowtrack[1]+track)*tracksize;
  601.  
  602.                 if (drives==1) {
  603.                     lsprintf(infobuf,string_table[STR_DISKCOPY_INSERTDEST],dest);
  604.                     border_text(reqbase,border,infobuf);
  605.                     drive_motor(device_req[0],0);
  606.                     if (!(check_error(reqbase,infobuf,STR_PROCEED)) ||
  607.                         !(check_disk(reqbase,device_req[1],dest,1))) {
  608.                         err=ERROR_ABORTED;
  609.                         abort=1;
  610.                         break;
  611.                     }
  612.                     drive_motor(device_req[0],1);
  613.                 }
  614.  
  615.                 for (curtrack=0;curtrack<trackcount;curtrack++) {
  616.  
  617.                     if (!check) {
  618.                         lsprintf(infobuf,string_table[STR_DISKCOPY_WRITING],
  619.                             track+curtrack,numtracks-curtrack-track-1);
  620.                         border_text(reqbase,border,infobuf);
  621.  
  622.                         if (check_abort(reqbase->rb_window)) {
  623.                             abort=1;
  624.                             err=ERROR_ABORTED;
  625.                             break;
  626.                         }
  627.  
  628.                         FOREVER {
  629.                             device_req[1]->iotd_Req.io_Command=TD_FORMAT;
  630.                             device_req[1]->iotd_Req.io_Data=(APTR)&buffer[curtrack*tracksize];
  631.                             device_req[1]->iotd_Req.io_Offset=offset;
  632.                             device_req[1]->iotd_Req.io_Length=tracksize;
  633.  
  634.                             if (!(DoIO((struct IORequest *)device_req[1]))) {
  635.                                 if (!verifybuffer) break;
  636.                                 device_req[1]->iotd_Req.io_Command=CMD_UPDATE;
  637.                                 if (!(DoIO((struct IORequest *)device_req[1]))) break;
  638.                             }
  639.  
  640.                             lsprintf(infobuf,string_table[STR_DISKCOPY_WRITEERROR],track+curtrack);
  641.                             border_text(reqbase,border,infobuf);
  642.                             if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  643.                                 abort=1;
  644.                                 err=ERROR_FAILED;
  645.                                 break;
  646.                             }
  647.                         }
  648.  
  649.                         if (abort) break;
  650.                     }
  651.  
  652.                     if (verifybuffer) {
  653.                         lsprintf(infobuf,string_table[STR_FORMAT_VERIFYING],
  654.                             track+curtrack,numtracks-curtrack-track-1);
  655.                         border_text(reqbase,border,infobuf);
  656.  
  657.                         FOREVER {
  658.                             device_req[1]->iotd_Req.io_Command=CMD_READ;
  659.                             device_req[1]->iotd_Req.io_Data=(APTR)verifybuffer;
  660.                             device_req[1]->iotd_Req.io_Offset=offset;
  661.                             device_req[1]->iotd_Req.io_Length=tracksize;
  662.  
  663.                             if (!(DoIO((struct IORequest *)device_req[1]))) {
  664.                                 for (a=0,b=curtrack*cmpsize;a<cmpsize;a++,b++) {
  665.                                     if (verifybuffer[a]!=cmpbuffer[b]) break;
  666.                                 }
  667.                                 if (a==cmpsize) break;
  668.                                 lsprintf(infobuf,string_table[STR_FORMAT_VERIFYERROR],track+curtrack);
  669.                                 err=ERROR_VERIFY;
  670.                             }
  671.                             else {
  672.                                 lsprintf(infobuf,string_table[STR_DISKCOPY_READERROR],track+curtrack);
  673.                                 err=ERROR_FAILED;
  674.                             }
  675.  
  676.                             border_text(reqbase,border,infobuf);
  677.                             if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  678.                                 abort=1;
  679.                                 break;
  680.                             }
  681.                             err=0;
  682.                         }
  683.  
  684.                         if (abort) break;
  685.                     }
  686.  
  687.                     offset+=tracksize;
  688.                 }
  689.  
  690.             }
  691.  
  692.             for (a=0;a<drives;a++) drive_motor(device_req[a],0);
  693.  
  694.             switch (err) {
  695.                 case 0:
  696.                     if (bump && !check) {
  697.                         border_text(reqbase,border,string_table[STR_BUMPING_NAME]);
  698.                         inhibit_drive(dest,FALSE);
  699.                         bump_disk_name(dest);
  700.                     }
  701.                     txt=STR_SUCCESS;
  702.                     break;
  703.                 case ERROR_ABORTED: txt=STR_ABORTED; break;
  704.                 case ERROR_FAILED: txt=STR_FAILED_ERROR; break;
  705.                 case ERROR_VERIFY: txt=-1; break;
  706.             }
  707.  
  708.             inhibit_drive(source,FALSE);
  709.             if (drives==2) inhibit_drive(dest,FALSE);
  710.         }
  711.         else txt=STR_ABORTED;
  712.  
  713.         EndRequest(&busyreq,reqbase->rb_window);
  714.         ClearPointer(reqbase->rb_window);
  715.     }
  716.     else txt=STR_NODEVICE_ERROR;
  717.  
  718.     if (txt>-1) border_text(reqbase,border,string_table[txt]);
  719.  
  720.     for (a=0;a<2;a++) {
  721.         if (device_req[a]) {
  722.             CloseDevice((struct IORequest *)device_req[a]);
  723.             LDeleteExtIO((struct IORequest *)device_req[a]);
  724.         }
  725.         if (device_port[a]) LDeletePort(device_port[a]);
  726.     }
  727.  
  728.     LFreeRemember(&memkey);
  729.     return((txt==STR_SUCCESS));
  730. }
  731.  
  732. void bump_disk_name(disk)
  733. char *disk;
  734. {
  735.     if (IconBase) {
  736.         struct Process *myproc;
  737.         APTR wsave;
  738.         BPTR lock;
  739.  
  740.         myproc=(struct Process *)FindTask(NULL);
  741.         wsave=myproc->pr_WindowPtr;
  742.         myproc->pr_WindowPtr=(APTR)-1;
  743.  
  744.         if (lock=Lock(disk,ACCESS_READ)) {
  745.             struct FileInfoBlock __aligned info;
  746.             char namebuf[32];
  747.             struct MsgPort *port;
  748.  
  749.             Examine(lock,&info);
  750.             UnLock(lock);
  751.  
  752.             BumpRevision(namebuf,info.fib_FileName);
  753.  
  754.             if (port=(struct MsgPort *)DeviceProc(disk)) {
  755.                 char __aligned bstr_name[36];
  756.                 ULONG arg;
  757.  
  758.                 bstr_name[0]=strlen(namebuf);
  759.                 strcpy(&bstr_name[1],namebuf);
  760.                 arg=(ULONG)bstr_name>>2;
  761.                 SendPacket(port,ACTION_RENAME_DISK,&arg,1);
  762.             }
  763.         }
  764.         myproc->pr_WindowPtr=wsave;
  765.     }
  766. }
  767.